package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.dao.IStrategySearchDAO;
import cn.wolfcode.luowowo.search.query.SearchQueryObject;
import cn.wolfcode.luowowo.search.query.StrategySearchQuery;
import cn.wolfcode.luowowo.search.service.IStrategySearchService;
import cn.wolfcode.luowowo.search.template.StrategyTemplate;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregation;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeValuesSourceBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;

import java.util.*;

@Service
public class StrategySearchServiceImpl implements IStrategySearchService {
    @Autowired
    private IStrategySearchDAO strategySearchDAO;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    private TransportClient client;

    @Override
    public void createIndex() {
        elasticsearchTemplate.createIndex(StrategyTemplate.class);
        elasticsearchTemplate.putMapping(StrategyTemplate.class);
    }

    @Override
    public void save(StrategyTemplate template) {
        strategySearchDAO.save(template);
    }

    @Override
    public List<Map<String, Object>> queryThemeCommends() {


        List<StatisVO> themeVos = this.groupStatis("themeGroup", "themeId", "themeName", null);
        //截取前10
        if (themeVos.size() > 0) {
            themeVos.subList(0, 10);
        }

        //外层List
        List<Map<String, Object>> data = new ArrayList<>();

        //内层  :  主题  +  目的地集合
        Map<String, Object> map;
        for (StatisVO themeVo : themeVos) {
            List<StatisVO> list = queryDestByThemeId(themeVo.getId());
            map = new HashMap<>();
            map.put("theme", themeVo);   //主题
            map.put("dest", list);       //目的地
            data.add(map);
        }

        return data;
    }

    public List<StatisVO> queryStrategyCondition(int conditionTyprTheme) {

        String idField = "";
        String nameField = "";

        //查询过滤条件
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if (conditionTyprTheme == SearchQueryObject.CONDITION_TYPR_ABROAD) {
            //countryId
            //counttryName
            idField = "countryId";
            nameField = "countryName";
            boolQuery.mustNot(QueryBuilders.termQuery("countryId", 1));
            //拼接条件 : counttryID <> 1

        } else if (conditionTyprTheme == SearchQueryObject.CONDITION_TYPR_UN_ABROAD) {
            //provinceId
            //provinceName
            //拼接条件:  countryId == 1
            idField = "provinceId";
            nameField = "provinceName";
            boolQuery.must(QueryBuilders.termQuery("countryId", 1));
        } else if (conditionTyprTheme == SearchQueryObject.CONDITION_TYPR_THEME) {
            //themeId
            //themeName
            idField = "themeId";
            nameField = "themeName";
        }
        List<StatisVO> themeVos = this.groupStatis("conditionGroup", idField, nameField, boolQuery);
        return themeVos;
    }

    @Override
    public Page<StrategyTemplate> query(StrategySearchQuery qo) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if (qo.getType() == SearchQueryObject.CONDITION_TYPR_ABROAD) {
            boolQuery.must(QueryBuilders.termQuery("countryId", qo.getTypeValue()));
        } else if (qo.getType() == SearchQueryObject.CONDITION_TYPR_UN_ABROAD) {
            //provinceId
            boolQuery.must(QueryBuilders.termQuery("provinceId", qo.getTypeValue()));
        } else if (qo.getType() == SearchQueryObject.CONDITION_TYPR_THEME) {
            //themeId
            //themeName
            boolQuery.must(QueryBuilders.termQuery("themeId", qo.getTypeValue()));
        }
        Page<StrategyTemplate> search = strategySearchDAO.search(boolQuery, qo.getPageable());
        return search;
    }

    @Override
    public Page<StrategyTemplate> queryByDestId(StrategySearchQuery qo) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if (qo.getDestId() != -1) {
            boolQuery.must(QueryBuilders.termQuery("destId", qo.getDestId()));
        }
        return strategySearchDAO.search(boolQuery,qo.getPageableWithSort());
    }


    private List<StatisVO> queryDestByThemeId(Long themeId) {
        List<StatisVO> list = new ArrayList<>();
        List<String> names = new ArrayList<>();
        Iterable<StrategyTemplate> dests = strategySearchDAO.search(QueryBuilders.termQuery("themeId", themeId));
        dests.forEach(s -> {
            if (!names.contains(s.getDestName())) {
                StatisVO vo = new StatisVO();
                vo.setId(s.getDestId());
                vo.setName(s.getDestName());
                list.add(vo);
                names.add(s.getDestName());
            }
        });
        return list;
    }


    //分组统计
    private List<StatisVO> groupStatis(String compositeName, String idField, String nameField, BoolQueryBuilder query) {
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();

        //构建分组字段对象
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");  //名字
        idSource.field(idField);  //分组字段
        idSource.missingBucket(true);   //忽略不满足条件bucket

        //构建分组字段对象
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");  //名字
        nameSource.field(nameField);  //分组字段
        nameSource.missingBucket(true);   //忽略不满足条件bucket

        sources.add(idSource);
        sources.add(nameSource);
        //参数数1:分组名称
        //参数2:分组字段集合
        CompositeAggregationBuilder builder = new CompositeAggregationBuilder(compositeName, sources);


        //查询请求对象
        SearchRequest request = new SearchRequest(StrategyTemplate.INDEX_NAME);

        if (query == null) {
            query = QueryBuilders.boolQuery();
        }

        //设置类型
        request.types(StrategyTemplate.TYPE_NAME);

        request.source(new SearchSourceBuilder().aggregation(builder)
                .size(0)
                .query(query)
        );
        //发送请求
        SearchResponse response = this.client.search(request).actionGet();

        Aggregations aggregations = response.getAggregations();
        //聚合查询分组对象
        CompositeAggregation themeGroup = aggregations.get(compositeName);


        List<? extends CompositeAggregation.Bucket> buckets = themeGroup.getBuckets();

        List<StatisVO> themeVos = new ArrayList<>();
        for (CompositeAggregation.Bucket bucket : buckets) {
            StatisVO vo = new StatisVO();

            Map<String, Object> key = bucket.getKey();

            long count = bucket.getDocCount();

            //封装StatisVO对象数据
            vo.setId(Long.valueOf(key.get("id").toString()));
            vo.setName(key.get("name").toString());
            vo.setCount(count);
            themeVos.add(vo);
        }

        //排序
        Collections.sort(themeVos, new Comparator<StatisVO>() {
            public int compare(StatisVO o1, StatisVO o2) {
                return o2.getCount().compareTo(o1.getCount());
            }
        });

        return themeVos;
    }


}
